import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

# 构建实验数据
train_x = np.linspace(-1, 1, 100)
# y = 2 * x + b
train_y = 2. * train_x + np.random.randn(*train_x.shape) * 0.3

# 可视化
plt.plot(train_x, train_y, 'b--')
plt.legend("y=2*x+b")
plt.show()

# 创建模型

# 占位符
X = tf.placeholder(tf.float32)
Y = tf.placeholder(tf.float32)
# 模型参数
weights = tf.Variable(tf.random_normal([1]), name='weights')
biases = tf.Variable(tf.zeros([1]), name='biases')

z = tf.multiply(X, weights) + biases

# 构建损失函数
loss = tf.reduce_mean(tf.square(Y - z))
# tf.summary.scalar('loss', loss)
# 定义学习率
learning_rate = 0.01
# 构建优化函数
optimizer = tf.train.GradientDescentOptimizer(learning_rate)
# 最小化损失函数
train = optimizer.minimize(loss)

# 初始化所有变量
init = tf.global_variables_initializer()

# 定义 epoch
training_epochs = 20
# 每隔两步显示一次中间值
display_step = 2

# 存放批次值和损失值
plot_data = {'batchsize': [], 'loss': []}


def moving_average(a, w=10):
    if len(a) < w:
        return a[:]
    return [val if idx < w else sum(a[(idx - w):idx]) / w for idx, val in enumerate(a)]


# 启动Session
with tf.Session() as sess:
    # 初始化全局变量
    sess.run(init)

    # 向模型中 feed 数据
    for epoch in range(training_epochs):
        for (x, y) in zip(train_x, train_y):
            feed_dict = {X: x, Y: y}
            sess.run(train, feed_dict=feed_dict)

        # 显示训练中的数据
        if epoch % display_step == 0:
            loss_ = sess.run(loss, feed_dict={X: train_x, Y: train_y})
            print('epoch:', epoch + 1, 'loss = ', loss_, 'weights=', sess.run(weights), 'biases=', sess.run(biases))
            if not loss == 'NA':
                plot_data['batchsize'].append(epoch)
                plot_data['loss'].append(loss_)

    print('Finished...')
    print('loss=', sess.run(loss, feed_dict={X: train_x, Y: train_y}), 'weights=',
          sess.run(weights), 'biases=', sess.run(biases))

    print('x=0.2, z=', sess.run(z, feed_dict={X: 0.2}))

    # 可视化
    plt.plot(train_x, train_y, 'ro', label='Original Data')
    plt.plot(train_x, sess.run(weights)*train_x + sess.run(biases), label='FittedLine')
    plt.legend()
    plt.show()

    plot_data['avgloss']=moving_average(plot_data['loss'])
    plt.subplot(111)
    plt.plot(plot_data['batchsize'], plot_data['avgloss'], 'b--')
    plt.xlabel('Minibatch number')
    plt.ylabel('Loss')
    plt.title('Minibatch run vs Minibatch loss')
    plt.show()














